package cn.labbook.bluetooth.controller;


import cn.labbook.bluetooth.common.ResultDto;
import cn.labbook.bluetooth.common.TokenManager;
import cn.labbook.bluetooth.constant.AdminConstant;
import cn.labbook.bluetooth.constant.AmmeterConstant;
import cn.labbook.bluetooth.entity.*;
import cn.labbook.bluetooth.entity.excel.AmmeterTemplate;
import cn.labbook.bluetooth.entity.excel.CadeTemplate;
import cn.labbook.bluetooth.entity.excel.PayTemplate;
import cn.labbook.bluetooth.service.*;
import cn.labbook.bluetooth.util.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lowagie.text.Image;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.codec.binary.Base64;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author lonzy
 * @since 2019-03-26
 */
@Controller
@RequestMapping("//ammeter")
public class AmmeterController extends AbstractController {
    @Autowired
    IAmmeterService ammeterService;
    @Autowired
    IAdminService adminService;
    @Autowired
    IUserService userService;
    @Autowired
    ITenantPayService tenantPayService;
    @Autowired
    IConstantService constantService;

    @RequestMapping("add")
    @ResponseBody
    public ResultDto add(Ammeter ammeter) {
        String ammeterId = ammeter.getAmmeterId();
        if (ammeter.getAmmeterId().length() != 12) {
            return fail("电表序列号长度不正确，请核实");
        }
        String substring = ammeter.getAmmeterId().substring(0, 4);
        if (!substring.equals(TokenManager.getToken().getAdminId())) {
            return fail("电表序列号前四位厂家固定序号不正确，请核实");
        }
        ammeter.setCreateTime(new Date());
//        ammeter.setAdminId(TokenManager.getToken().getAdminId());
        ammeter.setManufacturersId(TokenManager.getToken().getAdminId());
        ammeter.setStatus(AmmeterConstant.NOTACTIVATE);
        ammeter.setIsSkimp(AmmeterConstant.IsSkimp.YES);
        ammeter.setAmount((double) 0);
        ammeter.setBalance((double) 0);
        ammeter.setDayPrice((double) 0);
        ammeter.setNightPrice((double) 0);
        return ammeterService.save(ammeter) ? success() : fail();
    }

    @RequestMapping("payRate")
    @ResponseBody
    public ResultDto payRate(String payRate,String adminId) {
        double pp = Double.valueOf(payRate);
        Admin admin = adminService.getById(adminId);
        admin.setPayRate(pp);
        return adminService.updateById(admin)?success():fail();
    }

    @RequestMapping("serverSet")
    @ResponseBody
    public ResultDto serverSet(String payPrice) {
        double pp = Double.valueOf(payPrice);
        if (TokenManager.getToken().getAdmin().getPermission() == AdminConstant.permission.NO && TokenManager.getToken().getAdmin().getAdminStatus() != AdminConstant.position.ZK) {
            return fail("您没有修改权限");
        }
        LambdaQueryWrapper<Constant> lambda = new QueryWrapper<Constant>().lambda();
        lambda.eq(Constant::getK,"serverPrice");
        Constant one = constantService.getOne(lambda);
        if(pp<one.getV()){
            return fail("设置失败，设置费率不能小于默认费率");
        }
        Admin admin = TokenManager.getToken().getAdmin();
        admin.setPayRate(pp);
//        int a = 1;
//        JSONArray objects = JSONArray.parseArray(serverData);
//        for (int i = 0; i < objects.size(); i++) {
//            //得到对象
//            JSONObject ammeter1 = objects.getJSONObject(i);
//            ammeter.setAmmeterId(ammeter1.get("ammeterId").toString());
//            ammeterService.updateById(ammeter);
//            a++;
//        }
        return adminService.updateById(admin) ? success() : fail();
    }

    @RequestMapping("edit")
    @ResponseBody
    public ResultDto edit(Ammeter ammeter) {
        return ammeterService.updateById(ammeter) ? success() : fail();
    }

    @RequestMapping("activate")
    @ResponseBody
    public ResultDto activate(Ammeter ammeter) throws ParseException {
        Ammeter a = ammeterService.getById(ammeter.getAmmeterId());
        if (a == null) {
            return fail("该电表不存在");
        }
        if (a.getStatus().equals(AmmeterConstant.ACTIVATE)) {
            return fail("该电表已被绑定");
        }
        ammeter.setActivateTime(new Date());
        ammeter.setStatus(AmmeterConstant.ACTIVATE);
        ammeter.setAmount(0.0);
        ammeter.setBalance(0.0);
        ammeter.setPayPrice(0.0);
        ammeter.setManagerId(TokenManager.getToken().getAdminId());
        ammeter.setServerStatus(AmmeterConstant.serverStatus.NOTEXPIRE);
        ammeter.setServerTime(new Date());
        ammeter.setOweStatus(AmmeterConstant.oweStatus.YES);
        return ammeterService.updateById(ammeter) ? success() : fail();
    }

    @RequestMapping("list")
    @ResponseBody
    public ResultDto list() {
        LambdaQueryWrapper<Ammeter> lambda = new QueryWrapper<Ammeter>().lambda();
        lambda.eq(Ammeter::getManagerId, TokenManager.getToken().getAdminId());
        List<Ammeter> list = ammeterService.list(lambda);
        return list.size() > 0 ? success(list) : fail("暂无数据");
    }

    @RequestMapping("notactivate")
    @ResponseBody
    public ResultDto notactivate(Ammeter ammeter) {
        ammeter.setStatus(AmmeterConstant.NOTACTIVATE);
        return ammeterService.updateById(ammeter) ? success() : fail();
    }

    //经销商分页查询
    @RequestMapping("adminPage")
    @ResponseBody
    public ResultDto adminPage(Page<Ammeter> page, Ammeter ammeter) {
        Admin admin1 = adminService.getById(TokenManager.getToken().getAdminId());
        boolean flag = (admin1.getPermission() == 1);
        LambdaQueryWrapper<Ammeter> lambda = new QueryWrapper<Ammeter>().lambda();
        ammeter.setAdminId(TokenManager.getToken().getAdminId());
        LambdaQueryWrapper<Admin> lambda1 = new QueryWrapper<Admin>().lambda();
        if (StringUtils.isNotBlank(ammeter.getUserName())) {
            lambda1.like(Admin::getAdminName, ammeter.getUserName());
            List<Admin> list = adminService.list(lambda1);
            list.forEach(admin -> {
                lambda.in(Ammeter::getManagerId, admin.getAdminId());
            });
        }
        lambda.eq(StringUtils.isNotBlank(ammeter.getStatus()), Ammeter::getStatus, ammeter.getStatus());
        lambda.eq(StringUtils.isNotBlank(ammeter.getAdminId()), Ammeter::getAdminId, ammeter.getAdminId());

        IPage<Ammeter> rusult = ammeterService.page(page, lambda);

        Constant serverPrice = constantService.getById("serverPrice");
        List<Ammeter> records = rusult.getRecords();
        records.forEach(ammeter1 -> {
            Admin byId = adminService.getById(ammeter1.getManagerId());
            if (byId != null) {
                ammeter1.setUserName(byId.getAdminName());
            }
            if (ammeter1.getPayPrice() != null) {
                if (ammeter1.getPayPrice() == 0 || !flag) {
                    ammeter1.setPayPrice(serverPrice.getV());
                } else if (serverPrice.getV() > ammeter1.getPayPrice()) {
                    ammeter1.setPayPrice(serverPrice.getV());
                }
            }
        });
        return rusult.getRecords().size() > 0 ? success(page) : fail("暂无数据");
    }

    //佐客电表分页查询
    @RequestMapping("zkPage")
    @ResponseBody
    public ResultDto zkPage(Page<Ammeter> page, Ammeter ammeter) {
        LambdaQueryWrapper<Ammeter> lambda = new QueryWrapper<Ammeter>().lambda();
        if (TokenManager.getToken().getAdmin().getAdminStatus() == AdminConstant.position.MANUFACTURERS) {
            lambda.eq(Ammeter::getManufacturersId, TokenManager.getToken().getAdminId());
        }
        lambda.eq(StringUtils.isNotBlank(ammeter.getAdminId()), Ammeter::getAdminId, ammeter.getAdminId());
        lambda.eq(StringUtils.isNotBlank(ammeter.getStatus()), Ammeter::getStatus, ammeter.getStatus());
        lambda.orderByAsc(Ammeter::getStatus);
        IPage<Ammeter> rusult = ammeterService.page(page, lambda);
        List<Ammeter> records = rusult.getRecords();
        records.forEach(ammeter1 -> {
            String adminId = ammeter1.getAdminId();
            Admin byId = adminService.getById(adminId);
            if (byId != null) {
                ammeter1.setAdminName(byId.getAdminName());
            }
        });
        return rusult.getRecords().size() > 0 ? success(page) : fail("暂无数据");
    }

    //房东电表分页查询
    @RequestMapping("page")
    @ResponseBody
    public ResultDto page(Page<Ammeter> page, Ammeter ammeter) {
        LambdaQueryWrapper<Ammeter> lambda = new QueryWrapper<Ammeter>().lambda();
        lambda.orderByAsc(Ammeter::getServerTime);
        lambda.eq(Ammeter::getStatus, AmmeterConstant.ACTIVATE);
        String adminId = TokenManager.getToken().getAdminId();
        lambda.eq(Ammeter::getManagerId, TokenManager.getToken().getAdminId());
        lambda.eq(StringUtils.isNotBlank(ammeter.getServerStatus()), Ammeter::getServerStatus, ammeter.getServerStatus());
        IPage<Ammeter> rusult = ammeterService.page(page, lambda);
        List<Ammeter> records = rusult.getRecords();
        Constant serverPrice = constantService.getById("serverPrice");
        records.forEach(ammeter1 -> {
            String adminId1 = ammeter1.getAdminId();
            Admin admin = adminService.getById(adminId1);
            boolean flag = (admin.getPermission() == 1);
            String userId = ammeter1.getUserId();
            User byId = userService.getById(userId);
            if (byId != null) {
                ammeter1.setUserName(byId.getUserName());
            }
            if (ammeter1.getPayPrice() != null) {
                if (ammeter1.getPayPrice() == 0 || !flag) {
                    ammeter1.setPayPrice(serverPrice.getV());
                } else if (serverPrice.getV() > ammeter1.getPayPrice()) {
                    ammeter1.setPayPrice(serverPrice.getV());
                }
            }
        });
        return rusult.getRecords().size() > 0 ? success(page) : fail("暂无数据");
    }

    //缴费
    @RequestMapping("pay")
    @ResponseBody
    public ResultDto pay(Ammeter ammeter) throws ParseException {
        ammeter.setServerTime(TimeUtils.addMonth(12, ammeter.getServerTime()));
        ammeter.setServerStatus(AmmeterConstant.serverStatus.NOTEXPIRE);
        return ammeterService.updateById(ammeter) ? success() : fail();
    }

    //下载导入电表模板
    @RequestMapping("template")
    public ResponseEntity<byte[]> template(String adminId) throws Exception {
        List<Ammeter> list = new ArrayList<>();
        Ammeter ammeter = new Ammeter();
        ammeter.setAdminId(adminId);
        ammeter.setAmmeterId(TokenManager.getToken().getAdminId());
        list.add(ammeter);
        List<AmmeterTemplate> collect = list.stream().map(l -> AmmeterTemplate.build(l)).collect(Collectors.toList());
        Map<String, String> m = new HashMap();
        m.put("adminId", "经销商ID");
        m.put("ammeterId", "电表号");
        return DownloadUtils.downloadExcel(AmmeterTemplate.class, collect, m, "导入电表模板");
    }

    //表格导入
    @RequestMapping("excelput")
    @ResponseBody
    public ResultDto excelput(MultipartFile file) throws Exception {
        ResultDto resultDto = new ResultDto();
        ExcelReader reader = ExcelReader.getDefaultExcelReader(file.getInputStream());
        Map<String, String> m = new HashMap();
        m.put("经销商ID", "adminId");
        m.put("电表号", "ammeterId");
        reader.setExcelNameMap(m);
        List<AmmeterTemplate> list = reader.readAsEntry(AmmeterTemplate.class);

        List<Ammeter> collect = list.stream()
                .map(l -> l.buildAmmeter(l))
                .filter(e -> {
                    String s = e.getAmmeterId().substring(0, 4);
                    String adminId = TokenManager.getToken().getAdminId();
                    boolean flag = e != null && e.getAmmeterId().length() <= 12 && s.equals(adminId);
                    return flag;
                })
                .collect(Collectors.toList());

        collect.forEach(ammeter -> {
            ammeter.setManufacturersId(TokenManager.getToken().getAdminId());
            ammeter.setStatus(AmmeterConstant.NOTACTIVATE);
            ammeter.setIsSkimp(AmmeterConstant.IsSkimp.YES);
            ammeter.setCreateTime(new Date());
            ammeter.setBalance((double) 0);
            ammeter.setAmount((double) 0);
            ammeter.setDayPrice((double) 0);
            ammeter.setNightPrice((double) 0);
        });
        String str = collect.get(0).getAdminId();
        for(int i=0;i<collect.size();i++){
            if(!str.equals(collect.get(i).getAdminId())){
                resultDto.setMsg("表格无法导入，经销商ID不一致");
                return resultDto;
            }
        }
        if (list.size() - collect.size() > 0) {
            resultDto.setMsg("有" + (list.size() - collect.size()) + "条数据显示电表序列号大于12位或者厂家前四位固定序号不正确，请核对");
        } else {
            resultDto.setCode(1);
        }
        for(int i=0;i<collect.size();i++){
            LambdaQueryWrapper<Ammeter> lambda = new QueryWrapper<Ammeter>().lambda().eq(Ammeter::getAmmeterId,collect.get(i).getAmmeterId());
            if(ammeterService.getOne(lambda)==null){
                collect.get(i).setManufacturersId(TokenManager.getToken().getAdminId());
                collect.get(i).setStatus(AmmeterConstant.NOTACTIVATE);
                collect.get(i).setIsSkimp(AmmeterConstant.IsSkimp.YES);
                collect.get(i).setCreateTime(new Date());
                collect.get(i).setBalance((double) 0);
                collect.get(i).setAmount((double) 0);
                collect.get(i).setDayPrice((double) 0);
                collect.get(i).setNightPrice((double) 0);
                ammeterService.save(collect.get(i));
            }
        }
        return resultDto;
    }

    //导出 充值模板
    @RequestMapping("payTemplate")
    public ResponseEntity<byte[]> payTemplate(String data) throws Exception {
        JSONArray objects = JSONArray.parseArray(data);
        List<Ammeter> list = new ArrayList<>();
        objects.forEach(s -> {
            Ammeter ammeter = new Ammeter();
            ammeter.setAdminId(s.toString());
            list.add(ammeter);
        });

        List<PayTemplate> collect = list.stream().map(l -> PayTemplate.build(l)).collect(Collectors.toList());
        Map<String, String> m = new HashMap();
//        m.put("adminId", "经销商ID");
        m.put("ammeterId", "电表ID");
        m.put("price", "充值金额");
        return DownloadUtils.downloadExcel(PayTemplate.class, collect, m, "导入电表充值模板");
    }

    //表格导入
    @RequestMapping("payexcelput")
    @ResponseBody
    public ResultDto payexcelput(MultipartFile file) throws Exception {

        ExcelReader reader = ExcelReader.getDefaultExcelReader(file.getInputStream());
        Map<String, String> m = new HashMap();
        m.put("电表号", "ammeterId");
        m.put("充值金额", "price");
        reader.setExcelNameMap(m);
        List<PayTemplate> list = reader.readAsEntry(PayTemplate.class);

        List<TenantPay> collect = list.stream()
                .map(l -> l.buildPay(l))
                .filter(e -> e != null)
                .collect(Collectors.toList());


        return tenantPayService.saveBatch(collect) ? success() : fail();
    }

    //房东更改余额
    @RequestMapping("editBalance")
    @ResponseBody
    public ResultDto editBalance(String ammeterId, Double balance) {
        Ammeter ammeter = ammeterService.getById(ammeterId);
        ammeter.setBalance(balance);
        return ammeterService.updateById(ammeter) ? success("更改成功，余额已改为" + balance) : fail("系统错误，请刷新重试");
    }

    @RequestMapping("reimbursement/set")
    @ResponseBody
    public ResultDto reimbursementSet(String serverData, Integer reimbursement) {
        JSONArray objects = JSONArray.parseArray(serverData);
        for (int i = 0; i < objects.size(); i++) {
            //得到对象
            JSONObject ammeterId = objects.getJSONObject(i);
            Ammeter ammeter = new Ammeter();
            ammeter.setIsSkimp(reimbursement);
            ammeter.setAmmeterId(ammeterId.get("ammeterId").toString());
            ammeterService.updateById(ammeter);
        }
        return success();
    }

    //批量生成二维码
    @RequestMapping("code")
    public void batchCode(MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws Exception {
        ExcelReader reader = ExcelReader.getDefaultExcelReader(file.getInputStream());
        Map<String, String> m = new HashMap();
        m.put("电表号", "ammeterId");
        reader.setExcelNameMap(m);
        List<CadeTemplate> list = reader.readAsEntry(CadeTemplate.class);
        List<Image> imgs = new ArrayList<>();
        list.forEach(cadeTemplate -> {
            imgs.add(CodeUtils.getQRCode(this.qrcodestr(Base64.encodeBase64String(cadeTemplate.getAmmeterId().getBytes())), cadeTemplate.getAmmeterId()));
            imgs.add(CodeUtils.getQRCode(this.qrcodestr(Base64.encodeBase64String(cadeTemplate.getAmmeterId().getBytes())), cadeTemplate.getAmmeterId()));
            imgs.add(CodeUtils.getQRCode(this.qrcodestr(Base64.encodeBase64String(cadeTemplate.getAmmeterId().getBytes())), cadeTemplate.getAmmeterId()));
        });
        try {
            CreateWord.createDocContext(imgs, request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return;


    }

    //拼接二维码内容
    private String qrcodestr(String ammeterId) {
//        String s = "{\"manufacturersId\":\"" + TokenManager.getToken().getAdminId() + "\"," + "\"ammeterId\":\"" + ammeterId + "\"}";
        String s = "https://bluetooth.zoercn.com/bluetooth/assets/\""+ammeterId+"\"";
        return s;
    }

    /**
     * 二维码输出到文件
     * @return
     * */
    //批量生成二维码
//    @RequestMapping("code")
//    public File writeToFile(MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws Exception {
//        ExcelReader reader = ExcelReader.getDefaultExcelReader(file.getInputStream());
//        Map<String, String> m = new HashMap();
//        m.put("电表号", "ammeterId");
//        reader.setExcelNameMap(m);
//        List<CadeTemplate> list = reader.readAsEntry(CadeTemplate.class);
//        this.download(request,response,list);
//        list.forEach(cadeTemplate -> {
//            BufferedImage qrCodeToBuffer = CodeUtils.getQRCodeToBuffer(this.qrcodestr(Base64.encodeBase64String(cadeTemplate.getAmmeterId().getBytes())), cadeTemplate.getAmmeterId());
//            try {
//                File files = new File("D:\\uploadFile\\"+cadeTemplate.getAmmeterId()+".jpg");//自己的默认存储路径
//                ImageIO.write(qrCodeToBuffer, "jpg", files);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        });
//        return null;
//    }

    public void download(HttpServletRequest request, HttpServletResponse response,List<CadeTemplate> list){
        try {
            String downloadFilename = "二维码.zip";//文件的名称
            downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");//转换中文否则可能会产生乱码
            response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
            response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);// 设置在下载框默认显示的文件名
            ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
//            String[] files = new String[]{"http://xxxx/xx.jpg","http://xxx/xx.jpg"};
            for (int i=0;i<list.size();i++) {
//                URL url = new URL(files[i]);
                zos.putNextEntry(new ZipEntry(list.get(i).getAmmeterId()+".jpg"));
                //FileInputStream fis = new FileInputStream(new File(files[i]));
//                InputStream fis = url.openConnection().getInputStream();
                BufferedImage qrCodeToBuffer = CodeUtils.getQRCodeToBuffer(this.qrcodestr(Base64.encodeBase64String(list.get(i).getAmmeterId().getBytes())), list.get(i).getAmmeterId());
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                ImageIO.write(qrCodeToBuffer, "jpg", os);
                InputStream fis =new ByteArrayInputStream(os.toByteArray());
                byte[] buffer = new byte[1024];
                int r = 0;
                while ((r = fis.read(buffer)) != -1) {
                    zos.write(buffer, 0, r);
                }
                fis.close();
            }
            zos.flush();
            zos.close();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
